package feign

import (
	"context"
	"fmt"
	"gitee.com/kristas/booting-go/framework"
	"gitee.com/kristas/booting-go/framework/common/util/httpx"
	"gitee.com/kristas/booting-go/framework/web/feign"
	"gitee.com/kristas/booting-go/framework/web/resp"
	"gitee.com/kristas/booting-go/framework/web/rest"
	"gitee.com/kristas/booting-go/internal/demo/dto"
)

func init() {
	framework.Component(new(TestClientImpl))
}

type TestClient interface {
	FindAllUsers() ([]*dto.AccountDTO, error)
	GetUserById(ctx context.Context, username string) (*dto.AccountDTO, error)
	SaveUser(ctx context.Context, username string, employee *dto.AccountDTO) (resp.Response, error)
}

type TestClientImpl struct {
	feign.BaseClient
	Port         int `value:"server.port"`
	target       string
	findAllUsers rest.GET  `url:""`
	getUserById  rest.GET  `url:"/{username}" param:"[c context,username path]"`
	saveUser     rest.POST `url:"/{username}/save" param:"[c context,username path,user body]"`
}

func (c *TestClientImpl) Init() error {
	c.target = fmt.Sprintf("%s:%d/api/v1/users", c.Url(), c.Port)
	return nil
}

func (c *TestClientImpl) Url() string {
	return "http://localhost"
}

func (c *TestClientImpl) FindAllUsers() ([]*dto.AccountDTO, error) {
	request, err := httpx.NewRequest(c.findAllUsers.GetType(), c.target+"")
	if err != nil {
		return nil, err
	}
	response, err := request.Do()
	if err != nil {
		return nil, err
	}
	var result = make([]*dto.AccountDTO, 0)
	err = response.Bind(&result)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func (c *TestClientImpl) GetUserById(ctx context.Context, username string) (*dto.AccountDTO, error) {
	request, err := httpx.NewRequest(c.getUserById.GetType(), c.target+"/{username}")
	if err != nil {
		return nil, err
	}
	// path var
	err = request.WithOption(httpx.PathVar("username", username))
	if err != nil {
		return nil, err
	}
	response, err := request.Do()
	if err != nil {
		return nil, err
	}
	var result = new(dto.AccountDTO)
	err = response.Bind(result)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func (c *TestClientImpl) SaveUser(ctx context.Context, username string, employee *dto.AccountDTO) (resp.Response, error) {
	request, err := httpx.NewRequest(c.saveUser.GetType(), c.target+"/{username}/save")
	if err != nil {
		return nil, err
	}
	err = request.WithOption(httpx.PathVar("username", username))
	if err != nil {
		return nil, err
	}
	err = request.WithOption(httpx.Body(employee))
	if err != nil {
		return nil, err
	}
	response, err := request.Do()
	if err != nil {
		return nil, err
	}
	result := make(map[string]interface{})
	err = response.Bind(&result)
	if err != nil {
		return nil, err
	}
	return resp.New(result), nil
}
